MODULE GEM_DEMO;

IMPORT Rts,GEMDOS,
			 AES,rsrc,evnt,graf,menu,objc,wind,
			 VDI,v,vr,vrt,vs,vsf,vswr,vst,
			 alert,app,desk,dial,draw,err,gpb,inf,list,mouse,pop,pops,rsc,redraw,
			 select,tree,util,vwk,wdial,xform,xfsel,xmenu,xobj;
FROM SYSTEM IMPORT ADR,ADDRESS,CODE;

(* generated by RSC2MOD v3.10 (c) 1992 Christian Sprenger *)

CONST
	D1						= 	0;	(* form tree *)

	D2						= 	1;	(* form tree *)
	D2list				= 	3;
	D2vslid 			= 	4;
	D2arr 				= 	8;
	D2pop 				=  10;
	D2edit				=  11;
	D2hslid 			=  12;
	D2open1 			=  13;
	D2ok					=  14;
	D2cancel			=  15;

	Menue 				= 	2;	(* menu tree *)
	Mabout				= 	8;
	Mdial1				=  18;
	Mdial2				=  19;
	Mdial3				=  20;
	Mdial4				=  22;
	Mdial5				=  23;
	Mpopup				=  25;
	Mquit 				=  27;
	Mobject 			=  29;
	Mropt 				=  31;
	Tool0 				=  33;
	Tool9 				=  42;

	D3						= 	3;	(* form tree *)
	D3msgbox			= 	1;
	D3msg0				= 	2;
	D3msg4				= 	6;
	D3result			= 	7;
	D3tree				= 	8;
	D3object			= 	9;

	D4						= 	4;	(* form tree *)
	D4list				= 	6;
	D4vslid 			= 	7;
	D4arr 				=  11;
	D4pop 				=  13;
	D4hslid 			=  15;
	D4open5 			=  16;
	D4ok					=  17;
	D4canc				=  18;

	D5						= 	5;	(* form tree *)

	Popmenu 			= 	6;	(* form tree *)
	Pdial1				= 	3;
	Pdial2				= 	4;
	Pdial3				= 	5;
	Pdial4				= 	7;
	Pdial5				= 	8;

	D3menue 			= 	7;	(* menu tree *)
	M3about 			= 	7;
	M3d4					=  16;
	M3d5					=  17;
	M3pop 				=  19;
	M3quit				=  21;

	D3icon				= 	8;	(* form tree *)

	Desk					= 	9;	(* form tree *)
	Dwin1 				= 	1;
	Dwin2 				= 	2;
	Dclip 				= 	3;
	Dexit 				= 	4;
	Dtrash				= 	5;

	Setroll 			=  10;	(* form tree *)
	Break 				= 	4;
	Count 				= 	6;
	Rok 					= 	8;
	Rcanc 				= 	9;

	Aboutbox			=  11;	(* form tree *)
	Mosysbox			= 	7;
	Mosys 				= 	9;
	Imgbox				=  14;
	Img0					=  15;

	Form17				=  12;	(* form tree *)

	Form18a 			=  13;	(* form tree *)

	Form18b 			=  14;	(* form tree *)

	Form18c 			=  15;	(* form tree *)

	Form19				=  16;	(* form tree *)

	Form20				=  17;	(* form tree *)

	Form21				=  18;	(* form tree *)
	Arr21 				=  18;

	Form22				=  19;	(* form tree *)
	Pos22c				= 	9;
	Pos22b				=  12;
	Pos22a				=  15;
	Slide22b			=  16;
	Slide22c			=  17;
	Slide22a			=  18;

	Form23a 			=  20;	(* form tree *)

	Form23b 			=  21;	(* form tree *)

	Form12				=  22;	(* form tree *)
	Menu12				= 	4;

	Menu					=  23;	(* form tree *)
	Mleft 				= 	2;
	Mright				= 	3;
	Msubmenu			= 	5;
	Mundo 				= 	7;

	Submenu 			=  24;	(* form tree *)
	Smalert 			= 	2;
	Smxfsel 			= 	3;
	Smselect			= 	4;
	Smdialef			= 	6;
	Smdialbo			= 	7;
	Smroll0 			= 	9;
	Smroll1 			=  14;

	Formedit			=  25;	(* form tree *)
	Sel_obj 			= 	8;
	Editable			= 	9;
	Errdo 				=  12;

	Form24				=  26;	(* form tree *)
	Sbox0n				= 	7;
	Vslid0n 			= 	8;
	Sbox1 				= 	9;
	Vslid1				=  10;
	Sbox01				=  11;
	Vslid01 			=  12;
	Sbox0 				=  14;
	Vslid0				=  15;
	Hslid0n 			=  16;

	Icons 				=  27;	(* form tree *)
	Head0 				=  12;

	Form25				=  28;	(* form tree *)
	Peol					=  14;
	Pdrv					=  17;

	Form26				=  29;	(* form tree *)

	Choice				=  30;	(* form tree *)
	Cleft 				= 	2;
	Cquit 				= 	3;
	Cright				= 	4;

	Test					= 	0;	(* free image *)

	MaxTree  =	30;
	MaxFrImg =	 0;

(* END OF RESOURCE DEFINITIONS ---------------------------*)

CONST
(*$? gpb.PIN:
	TMax = 14; (* Dialoge 0..TMax *)
*)
(*$? ~gpb.PIN:
	TMax = 13; (* Dialoge 0..TMax *)
*)

VAR 							(* globale Variablen f�r DoTimer()-Animation *)
	Inc,						(* vorw„rts oder r�ckw„rts *)
	Img: SHORTINT;	(* aktuelle Bildnummer *)

(*$E+*)
PROCEDURE DoTimer(Usr: ADDRESS; Tree: objc.tpTree);
(* zeigt Images in der Reihenfolge 0-1-2-3-4-3-2-1-0-.... *)
BEGIN
	IF (Img=0) OR (Img=4) THEN Inc := -Inc END;
	tree.setf(Tree,Img0+Img,objc.HideTree);
	INC(Img,Inc);
	tree.clrf(Tree,Img0+Img,objc.HideTree);
	objc.draw(Tree,Imgbox,10,Tree^[0].pos);
END DoTimer;

PROCEDURE DoAbout();
VAR
	d: dial.tDial;
	(*$R+*)i: SHORTINT;
BEGIN
	desk.select(Dwin2);
	dial.init(d,Aboutbox);
	dial.create(d);
	FOR i:=0 TO 4 DO
		d.Tree^[Img0+i].pos.y := d.Tree^[Img0].pos.y;
		tree.chgf(d.Tree,Img0+i,objc.HideTree,i>0)
	END;
	d.Tree^[Imgbox].pos.h := d.Tree^[Img0].pos.h;
	WITH d.Tree^[Mosys].pos DO
		y := (d.Tree^[Mosysbox].pos.h - h) DIV 2
	END;
	Img := 0; Inc := -1;
	dial.open(d);
	i :=dial.xdo(d,0,FALSE,xform.NoKey,DoTimer,100);
	EXCL(d.Tree^[i].state,objc.Selected);
	dial.delete(d);
	desk.deselect(Dwin2);
END DoAbout;

(*--------------------------------------------------------*)
(*$E+*)
PROCEDURE DrawIt(Nr: LONGINT;
							 HOff: LONGINT;
							 Rect: AES.tRect;
							 Clip: AES.tRect;
					 Selected: BOOLEAN;
						UserVal: ADDRESS);
VAR
	str: ARRAY[0..65] OF CHAR;
	i: SHORTINT;
	pxy: ARRAY[0..1] OF VDI.tPoint;
BEGIN
	WITH Clip DO
		pxy[0].x := x;
		pxy[0].y := y;
		pxy[1].x := x+w-1;
		pxy[1].y := y+h-1;
		vs.clip(vwk.hdl,TRUE,pxy);
	END;
	WITH Rect DO
		str := ' __. line of list ';
		str[1] := CHR(Nr DIV 10 + 60B);
		str[2] := CHR(Nr MOD 10 + 60B);
		str[HOff + w DIV vwk.charw] := 0C;
		WITH Rect DO
			IF Selected THEN
				pxy[0].x := x;	 pxy[0].y := y;
				pxy[1].x := x+w-1; pxy[1].y := y+h-1;
				VOID(vsf.color(vwk.own,VDI.Black));
				vr.recfl(vwk.own,pxy);
				VOID(vsf.color(vwk.own,VDI.White));
				i := vswr.mode(vwk.own,vswr.XOR);
				v.gtext(vwk.own,x,y,AES.tpStr(ADR(str[HOff]))^); (* XOR ausgeben! *)
				i := vswr.mode(vwk.own,vswr.Replace);
			ELSE
				v.gtext(vwk.own,x,y,AES.tpStr(ADR(str[HOff]))^); (* XOR ausgeben! *)
			END
		END;
	END;
END DrawIt;

VAR
	p2: pops.tPops;
	MCnt: SHORTINT;

(*$E+*)
PROCEDURE React(WD: dial.tpDial; obj: SHORTINT; VAR msg: dial.tMsg);
VAR
	dnr,i: SHORTINT;
	str: ARRAY[0..9] OF CHAR;
	nr,typ: ARRAY[0..15] OF CHAR;
BEGIN
	IF WD=ADR(d1) THEN dnr := 1
	ELSIF WD=ADR(d2) THEN dnr := 2
	ELSE dnr := 3 END;
	str := FORM(dnr); tree.setstr(d3.Tree,D3tree,str);
	IF obj>=0 THEN
		str := FORM(obj);
		tree.setstr(d3.Tree,D3object,str);
	ELSE
		tree.setstr(d3.Tree,D3object,'--');
		FOR i:=D3msg0 TO D3msg4 - 1 DO
			tree.getstr(d3.Tree,i+1,typ); tree.setstr(d3.Tree,i,typ)
		END;
		CASE msg.type OF
		|evnt.Closed:
			wdial.close(WD^);
			typ := 'Closed'
		|evnt.Redraw:
			typ := 'Redraw'
		|evnt.Selected:
			typ := 'Selected'
		|evnt.Untopped:
			typ := 'Untopped'
		|evnt.OnTop:
			typ := 'OnTop'
		|evnt.CT_Update:
			typ := 'CT_Update'
		|evnt.CT_Move:
			typ := 'CT_Move'
		|evnt.CT_Newtop:
			typ := 'CT_Newtop'
		|evnt.CT_Key:
			typ := 'CT_Key'
		ELSE
			typ := FORM('Msg #',msg.type)
		END;
		nr := FORM(' 0 ',typ);
		IF MCnt>9 THEN nr[0] := CHR(MCnt DIV 10 + 60B) END;
		nr[1] := CHR(MCnt MOD 10 + 60B);
		tree.setstr(d3.Tree,D3msg4,nr);
		MCnt := (MCnt+1) MOD 100;
		wdial.draw_obj(d3,D3msgbox,-1);
		IF (msg.type=evnt.Selected) & (msg.id=-d3.WHdl) THEN
			CASE msg.entry OF
			|M3about: DoAbout
			|M3d4 	: DoDial(0,D[0])
			|M3d5 	: DoDial(1,D[1])
			|M3pop	: DoDial(2,D[2])
			|M3quit : Quit := TRUE
			END;
			wdial.tnormal(d3,msg.title,TRUE)
		END
	END;
	wdial.draw_obj(d3,D3result,-1);
	WITH WD^ DO
		IF dnr=2 THEN
			CASE obj OF
			|D2list,
			 D2vslid,
			 D2hslid: list.handle(d2,D2list,obj)
			|D2arr: VOID(util.arr_chgval(d2,D2arr))
			|D2pop: pops.handle(d2,p2)
			|D2ok,D2cancel:
				wdial.close(d2)
			|D2open1:
				DoMenu(4,Mdial1);
			ELSE
			END
		ELSIF dnr=1 THEN
			IF (obj=-1) & (msg.type=evnt.Closed) OR (obj>0) THEN
				CloseD1
			END
		END;
		IF (obj>=0) & tree.tests(Tree,obj,objc.Selected) THEN
			tree.clrs(Tree,obj,objc.Selected);
			IF WHdl>=0 THEN
				redraw.tree(WHdl,Tree,obj,8,Rect)
			END
		END
	END
END React;
(*$E-*)

VAR
	Sel4: ARRAY[0..1] OF BITSET;
	p4: pops.tPops;

(*$E+*)
PROCEDURE DoDial(idx: SHORTINT; VAR d: dial.tDial);
VAR
	rtree: objc.tpTree;
	res,x,y: SHORTINT;
	dum: BITSET;
	Delay,Cnt: SHORTINT;
BEGIN
	WITH d DO
		IF idx#2 THEN (* Dialoge *)
			dial.create(d);
			Delay := inf.xmenuDelay;
			Cnt := cnt;
			IF idx=0 THEN (* Dialog 4 *)
				list.create(d,D4list,D4vslid,vwk.charh,0,32,DrawIt,
					ADR(Sel4),0,xobj.Sel0_n,NIL);
				list.create_hor(d,D4list,D4hslid,vwk.charw,0,18);
				util.arr_setval(D[0],D4arr,0,-999,999);
				pops.create2(D[0],D4pop,0,pstr,p4);
			ELSIF idx=3 THEN (* RollMen�-Optionen *)
				util.arr_setval(d,Break,Delay,0,20);
				util.arr_setval(d,Count,Cnt,0,99);
			END;
			dial.open(d);
			LOOP
				res := dial.do(d,0);
				IF idx=0 THEN
					CASE res OF
					|D4list,
					 D4vslid,
					 D4hslid: list.handle(D[0],D4list,res)
					|D4arr: 	VOID(util.arr_chgval(D[0],D4arr))
					|D4pop: 	pops.handle(D[0],p4)
					|D4open5: DoDial(1,D[1]);
										wdial.deselect(D[0],D4open5)
					ELSE EXIT
					END
				ELSIF idx=1 THEN EXIT
				ELSIF idx=3 THEN
					CASE res OF
					|Break: Delay := util.arr_chgval(d,Break)
					|Count: Cnt := util.arr_chgval(d,Count);
					|Rok: 	inf.xmenuDelay := Delay;
									cnt := Cnt; xmenu.setroll(MenuTree,Tool0,cnt,GetItem);
									EXIT
					|Rcanc: EXIT
					END
				END;
			END;
			EXCL(Tree^[res].state,objc.Selected);
			dial.delete(d);
		ELSE (* Popup-Men�s *)
			pop.create(d);
			graf.mkstate(x,y,dum,dum);
			pop.open(d,x,y);
			pop.menu(d,TRUE,rtree,res);
			pop.delete(d);
			CASE res OF
			|Pdial1: OpenD1
			|Pdial2: IF wdial.open(d2,0) THEN END;
			|Pdial3: IF wdial.open(d3,0) THEN END;
			|Pdial4: DoDial(0,D[0])
			|Pdial5: DoDial(1,D[1])
			ELSE (* nichts, war Klick daneben *)
			END
		END;
	END
END DoDial;
(*$E-*)

PROCEDURE DoKey(key: AES.tKey; state: BITSET): BOOLEAN;
VAR
	ignored: BOOLEAN;
BEGIN
	IF evnt.Ctrl IN state THEN
		ignored := FALSE;
		CASE dial.key(key.scan) OF
		|'1': DoMenu(4,Mdial1);
		|'2': DoMenu(4,Mdial2);
		|'3': DoMenu(4,Mdial3);
		|'4': DoMenu(4,Mdial4);
		|'5': DoMenu(4,Mdial5);
		|'p': DoMenu(4,Mpopup);
		|'o': DoMenu(5,Mobject);
		|'q': DoMenu(4,Mquit);
		ELSE
			ignored := TRUE;
		END
	ELSE
		ignored := TRUE;
	END;
	RETURN ignored
END DoKey;

PROCEDURE OpenD1();
BEGIN
	IF ~d1.Open THEN wdial.level(TRUE) END;
	IF ~wdial.open(d1,0) THEN wdial.level(FALSE) END;
	menu.ienable(MenuTree,Mabout,~d1.Open);
	menu.ienable(MenuTree,Mdial2,~d1.Open);
	menu.ienable(D[2].Tree,Pdial2,~d1.Open);
	menu.ienable(D[2].Tree,Pdial3,~d1.Open);
END OpenD1;

PROCEDURE CloseD1();
BEGIN
	wdial.close(d1);
	wdial.level(FALSE);
	menu.ienable(MenuTree,Mabout,TRUE);
	menu.ienable(MenuTree,Mdial2,TRUE);
	menu.ienable(D[2].Tree,Pdial2,TRUE);
	menu.ienable(D[2].Tree,Pdial3,TRUE);
END CloseD1;

PROCEDURE DoMenu(title,entry: SHORTINT);
BEGIN
	menu.tnormal(MenuTree,title,FALSE);
	CASE entry OF
	|Mabout:	DoAbout
	|Mdial1:	OpenD1
	|Mdial2:	IF wdial.open(d2,0) THEN END;
	|Mdial3:	IF wdial.open(d3,0) THEN END;
	|Mdial4:	DoDial(0,D[0])
	|Mdial5:	DoDial(1,D[1])
	|Mpopup:	DoDial(2,D[2])
	|Mquit: 	Quit := TRUE
	|Mobject: DoDemo
	|Mropt: 	desk.select(Dwin1);
						DoDial(3,D[3]);
						desk.deselect(Dwin1);
	ELSE
	END;
	menu.tnormal(MenuTree,title,TRUE);
END DoMenu;

(*$E+*)
PROCEDURE GetItem(nr,cnt: SHORTINT;
								VAR item: xobj.tRStr;
							 VAR state: BITSET);
BEGIN
	IF nr<cnt THEN
		item := '  Item #00';
		item[8] := CHR(nr DIV 10 + 60B);
		item[9] := CHR(nr MOD 10 + 60B);
		state := {};
		IF nr MOD 4=0 THEN INCL(state,objc.Checked) END;
		IF nr MOD 5=4 THEN INCL(state,objc.Disabled) END;
	ELSE
		item := '  ---';
		state := {objc.Disabled};
	END
END GetItem;
(*$E-*)

(*------------------------- DESKTOP ICONS ----------------------------*)

VAR
	PAR: RECORD
		work: AES.tRect;
		X,Y: SHORTINT;
		pos: ARRAY[Dwin1..Dtrash] OF RECORD x,y: SHORTINT END;
	END;

PROCEDURE DoButton(X,Y,Clix: SHORTINT);
VAR
	icon: SHORTINT;
	MoState,KState: BITSET;
BEGIN
	IF desk.win()=wind.find(X,Y) THEN
		icon := objc.find(DeskTree,0,10,X,Y);
		IF icon>0 THEN
			IF Clix=1 THEN
				desk.move(icon)
			ELSE
				CASE icon OF
				|Dclip:  SaveDesk
				|Dexit:  Quit := TRUE
				|Dtrash: LoadDesk
				|Dwin1:  DoMenu(5,Mropt);
				|Dwin2:  DoMenu(3,Mabout);
				ELSE
				END
			END
		END
	END;
END DoButton;

PROCEDURE LoadDesk;
VAR
	(*$R+*)f: SHORTINT;
	(*$R+*)i: SHORTINT;
BEGIN
	f := GEMDOS.Fopen('GEM_DEMO.PAR',GEMDOS.ReadOnly);
	IF f>=0 THEN
		WITH PAR DO
			work.w := -1;
			VOID(GEMDOS.Fread(f,SIZE(PAR),ADR(PAR)));
			VOID(GEMDOS.Fclose(f));
			IF work.w>=0 THEN
				FOR i:=Dwin1 TO Dtrash DO
					desk.setpos(i,pos[i].x,pos[i].y)
				END;
			END
		END
	END;
END LoadDesk;

PROCEDURE SaveDesk;
VAR
	(*$R+*)f: SHORTINT;
	(*$R+*)i: SHORTINT;
BEGIN
	f := GEMDOS.Fcreate('GEM_DEMO.PAR',{});
	IF f>=0 THEN
		WITH PAR DO
			FOR i:=Dwin1 TO Dtrash DO
				desk.getpos(i,pos[i].x,pos[i].y)
			END;
			desk.getsize(work,X,Y);
			VOID(GEMDOS.Fwrite(f,SIZE(PAR),ADR(PAR)));
			VOID(GEMDOS.Fclose(f))
		END;
	END;
END SaveDesk;

(*--------------------------------------------------------------------*)

(*$E+*)
PROCEDURE DoObjKey(Usr: ADDRESS;
							 Tree: objc.tpTree;
					VAR state: BITSET;
						VAR key: AES.tKey;
				 VAR Status: xform.tXform): BOOLEAN;
VAR
	p: dial.tDial;
	res,x,y: SHORTINT;
	db: BITSET;
	cmd: BOOLEAN;
BEGIN
	IF SHORTINT(key)=-1 THEN
		res := evnt.button(1,{0,1},{},x,y,db,db);
		dial.init(p,Choice);
		pop.create(p);
		pop.open(p,x-p.Tree^[0].pos.w DIV 2,y - vwk.charh DIV 2);
		pop.menu(p,TRUE,p.Tree,res);
		pop.delete(p);
		key.char := 0C;
		CASE res OF
		|Cleft:  key.scan := CHR(48H); state := {evnt.Ctrl}
		|Cquit:  key.scan := CHR(61H); state := {}
		|Cright: key.scan := CHR(50H); state := {evnt.Ctrl}
		ELSE RETURN FALSE
		END
	END;
	cmd := TRUE;
	CASE key.scan OF
	|CHR(61H): TheTree := -1
	|CHR(48H): IF evnt.Ctrl IN state THEN
							 DEC(TheTree); IF TheTree<0 THEN TheTree := TMax END
						 ELSE cmd := FALSE END;
	|CHR(50H): IF evnt.Ctrl IN state THEN
							 INC(TheTree); IF TheTree>TMax THEN TheTree := 0 END
						 ELSE cmd := FALSE END;
	ELSE
		cmd := FALSE;
	END;
	IF cmd THEN
		WITH Status DO
			NextObj := 0;
			Cont := FALSE;
		END;
		RETURN TRUE
	ELSE RETURN FALSE
	END
END DoObjKey;

(*$E+*)
PROCEDURE menuItem(i,count: SHORTINT; VAR txt: xobj.tRStr; VAR s: BITSET);
BEGIN
(* Da TMax > 4 = Anzahl der Zeilen im Rollmenu, kann die Abfrage entfallen *)
(***	 IF i<count THEN ***)
		txt := TTit[i]; s := {}
(***	 ELSE ***)
(***		 txt := '  leer'; s := {objc.Disabled} ***)
(***	 END; ***)
END menuItem;

(*- Zeichenfunktionen f�r ItemList-Objekte ---------------------------------*)

(*$E+*)
PROCEDURE DrawIt1(Nr: LONGINT;
								HOff: LONGINT;
								Rect: AES.tRect;
								Clip: AES.tRect;
						Selected: BOOLEAN;
								User: ADDRESS);
VAR
	str: ARRAY[0..65] OF CHAR;
	i: SHORTINT;
	pxy: ARRAY[0..1] OF VDI.tPoint;
BEGIN
	WITH Rect DO
		str := 'Dies ist die __-te Zeile dieses Beispiels.                       ';
		FOR i:=64 TO 64-Nr BY -1 DO str[i] := '_' END;
		str[13] := CHR(Nr DIV 10 + 60B);
		str[14] := CHR(Nr MOD 10 + 60B);
		str[HOff + w DIV vwk.charw] := 0C;
		WITH Rect DO
			IF Selected THEN
				pxy[0].x := x;	 pxy[0].y := y;
				pxy[1].x := x+w-1; pxy[1].y := y+h-1;
				VOID(vsf.color(vwk.own,VDI.Black));
				vr.recfl(vwk.own,pxy);
				VOID(vsf.color(vwk.own,VDI.White));
				i := vswr.mode(vwk.own,vswr.XOR);
				v.gtext(vwk.own,x,y,AES.tpStr(ADR(str[HOff]))^); (* XOR ausgeben! *)
				i := vswr.mode(vwk.own,vswr.Replace);
			ELSE
				v.gtext(vwk.own,x,y,AES.tpStr(ADR(str[HOff]))^); (* XOR ausgeben! *)
			END
		END;
	END;
END DrawIt1;

VAR
	IconTree: objc.tpTree;

PROCEDURE DrawIt2(Nr: LONGINT;
								HOff: LONGINT;
								Rect: AES.tRect;
								Clip: AES.tRect;
						Selected: BOOLEAN;
								User: ADDRESS);
VAR
	mfdb: VDI.tMFDB;
	pxy: ARRAY[0..3] OF VDI.tPoint;
	ColIdx: ARRAY[0..1] OF SHORTINT;
BEGIN
	WITH Rect DO
		draw.clear(x,y,w,h);
		WITH IconTree^[Nr+1].iconblk^ DO
			WITH mfdb DO
				W := icon.w; WdWidth := W DIV 16; H := icon.h;
				Stand := 0; NPlanes := 1; Addr := pdata;
			END;
			pxy[0].x := 0;						pxy[0].y := 0;
			pxy[1].x := icon.w-1; 		pxy[1].y := icon.h-1;
			pxy[2].x := x+8;					pxy[2].y := y;
			pxy[3].x := x+8+icon.w-1; pxy[3].y := y+icon.h-1;
			ColIdx[0] := 1; ColIdx[1] := 0;
			vrt.cpyfm(vwk.own,3,pxy,mfdb,vwk.scrMFDB,ColIdx);
			v.gtext(vwk.own,x+48,y+(h-vwk.charh) DIV 2,ptext^);
		END;
		IF Selected THEN draw.invert(x,y,w,h) END
	END
END DrawIt2;
(*$E-*)

(*- Funktionen f�r pops-Objekte --------------------------------------------*)

(*$E+*)
PROCEDURE GetDrv(Nr: SHORTINT;
						VAR str: STRING;
							 user: ADDRESS);
BEGIN
	str[0] := CHR(Nr+41H); str[1] := ':'; str[2] := 0C;
END GetDrv;
(*$E-*)

(*--------------------------------------------------------------------------*)

PROCEDURE Dialog(idx: SHORTINT);
VAR
	rTree: objc.tpTree;
	sub,popd,d: dial.tDial;
	i,val,rObj: SHORTINT;
	num: ARRAY[0..4] OF CHAR;
	bool: BOOLEAN;
	sel1: ARRAY[0..1] OF BITSET; (* 2x16=32 Bit *)
	EolP,DrvP: pops.tPops;
	EolS: ARRAY[0..15] OF CHAR;
BEGIN
	dial.init(d,idx);
	dial.create(d);
	CASE idx OF
	|Form21:	util.arr_setval(d,Arr21,0,-999,999)
	|Form22:	util.slide_set(d,Slide22a,0,15,5);
						util.slide_set(d,Slide22b,0,15,5);
						util.slide_set(d,Slide22c,3,7,1);
						tree.setstr(d.Tree,Pos22a,'0  ');
						tree.setstr(d.Tree,Pos22b,'0  ');
						rsrc.gaddr(rsrc.Tree,Icons,IconTree);
						d.Tree^[Pos22c].iconblk^.pdata := IconTree^[Head0+3].bitblk^.pdata;
	|Form24:	rsrc.gaddr(rsrc.Tree,Icons,IconTree);
						sel1[0] := {}; sel1[1] := {};
						list.create(d,Sbox0n,Vslid0n,vwk.charh,0,32,DrawIt1,
							ADR(sel1),0,xobj.Sel0_n,NIL);
						list.create_hor(d,Sbox0n,Hslid0n,vwk.charw,0,65);
						list.create(d,Sbox0,Vslid0,32,0,11,DrawIt2,NIL,1,xobj.Sel0,NIL);
						list.create(d,Sbox01,Vslid01,32,0,11,DrawIt2,NIL,1,xobj.Sel0_1,NIL);
						list.create(d,Sbox1,Vslid1,32,0,11,DrawIt2,NIL,1,xobj.Sel1,NIL);
	|Form25:	pops.create(d,Pdrv,2,i,16,GetDrv,NIL,DrvP);
						EolS := 'CrLf|Cr|Lf|0C';
						pops.create2(d,Peol,2,EolS,EolP);
	ELSE
	END;
	dial.open(d);
	IF idx=Form12 THEN (* Popup-Men�s abhandeln *)
		REPEAT
			i := dial.xdo(d,0,TRUE,DoObjKey,xform.NoTimer,0);
			IF i=Menu12 THEN
				dial.init(sub,Submenu);
				(* Optionen setzen *)
				tree.chgs(sub.Tree,Smdialef,objc.Checked,inf.dialEffect);
				tree.chgs(sub.Tree,Smdialbo,objc.Checked,~inf.dialBorder);
				pop.create(sub);
				xmenu.setroll(sub.Tree,Smroll0,TMax+1,menuItem);
				dial.init(popd,Menu);
				pop.create(popd);
				pop.chain(popd,Msubmenu,sub);
				pop.open(popd,xform.MoX-8,xform.MoY);
				pop.menu(popd,TRUE,rTree,rObj);
				pop.close(popd);

				IF (rTree=popd.Tree) & (rObj>0) THEN
					CASE rObj OF
					|Mleft:  DEC(TheTree); IF TheTree<0 THEN TheTree := TMax END
					|Mright: INC(TheTree); IF TheTree>TMax THEN TheTree := 0 END
					|Mundo:  TheTree := -1
					ELSE (* nix *)
					END;
					i := 0;
				ELSIF (rTree=sub.Tree) & (rObj>0) THEN
					CASE rObj OF
					|Smalert:  AlertDemo
					|Smxfsel:  DoXfsel
					|Smselect: DoSelect
					|Smroll0..Smroll1:
						TheTree := xmenu.getroll(sub.Tree,Smroll0,rObj); i := 0
					ELSE (* nix *)
					END;
				END;

				pop.delete(sub);
				pop.delete(popd);
				(* Optionen holen *)
				inf.dialEffect := tree.tests(sub.Tree,Smdialef,objc.Checked);
				inf.dialBorder := ~tree.tests(sub.Tree,Smdialbo,objc.Checked);
				tree.deselect(d.Tree,Menu12)
			END
		UNTIL i=0
	ELSIF idx=Form21 THEN (* PfeilBox abhandeln *)
		REPEAT
			i := dial.xdo(d,0,TRUE,DoObjKey,xform.NoTimer,0);
			IF i=Arr21 THEN VOID(util.arr_chgval(d,Arr21)) END
		UNTIL i=0
	ELSIF idx=Form24 THEN (* Listen abhandeln *)
		REPEAT
			i := dial.xdo(d,0,TRUE,DoObjKey,xform.NoTimer,0);
			CASE i OF
			|Sbox0n,Vslid0n,Hslid0n:
				list.handle(d,Sbox0n,i)
			|Sbox01,Vslid01:
				list.handle(d,Sbox01,i)
			|Sbox0,Vslid0:
				list.handle(d,Sbox0,i)
			|Sbox1,Vslid1:
				list.handle(d,Sbox1,i)
			ELSE
			END
		UNTIL i=0
	ELSIF idx=Form25 THEN (* Pops abhandeln *)
		LOOP
			i := dial.xdo(d,0,TRUE,DoObjKey,xform.NoTimer,0);
			CASE i OF
			|Peol: pops.handle(d,EolP)
			|Pdrv: pops.handle(d,DrvP)
			|0: EXIT
			ELSE
			END
		END;
	ELSIF idx=Formedit THEN
		val := -1;
		REPEAT
			i := dial.xdo(d,0,FALSE,DoObjKey,xform.NoTimer,0);
			IF i#0 THEN
				IF i=Errdo THEN
					err.do(d.Tree,Editable,
						'Dies ist eine 2-zeilige Fehlermeldung mit err.do().',
						'(Abbruch mit Taste oder Mausklick)');
				ELSE (* Sel_obj *)
					select.obj(d.Tree,
						'Auswahl',"Eine Auswahl an|Texten mittels|select.obj().|Ein einziger|Aufruf behandelt|diese Auswahlbox!",
							Editable,NIL,val);
				END;
				tree.deselect(d.Tree,i)
			END
		UNTIL i=0
	ELSIF idx=Form22 THEN
		REPEAT
			i := dial.xdo(d,0,FALSE,DoObjKey,xform.NoTimer,0);
			IF i=Slide22a THEN
				val := util.slide_get(d,Slide22a);
				num := FORM(val,' ');
				tree.setstr(d.Tree,Pos22a,num);
				tree.draw(d.Tree,Pos22a,0)
			ELSIF i=Slide22b THEN
				val := util.slide_get(d,Slide22b);
				num := FORM(val,' ');
				tree.setstr(d.Tree,Pos22b,num);
				tree.draw(d.Tree,Pos22b,0)
			ELSIF i=Slide22c THEN
				val := util.slide_get(d,Slide22c);
				d.Tree^[Pos22c].iconblk^.pdata := IconTree^[Head0+val].bitblk^.pdata;
				objc.draw(d.Tree,Pos22c,1,d.Rect)
			END;
		UNTIL i=0
	ELSE
		REPEAT
			i := dial.xdo(d,0,FALSE,DoObjKey,xform.NoTimer,0);
		UNTIL i=0 				 (* DoObjKey() liefert 0 f�r Links/Rechts/Undo *)
	END;
	dial.delete(d);
END Dialog;

(*-------- Demonstration der Alerts -----------------------------------------*)

(* das folgende Image wurde mit dem Programm IED erstellt *)

(*$E-*)(*$D-*)(*$S-*)
PROCEDURE FaceImg;
BEGIN;
	CODE(00000H,00008H,00000H,0001CH,00000H,0001EH,001FCH,0003FH);
	CODE(007FFH,0003FH,01FFFH,0E03EH,03FFFH,0F07CH,07FFFH,0F078H);
	CODE(07FFFH,0F878H,0FFFFH,0F870H,0FFFFH,0F870H,0FFFFH,0F800H);
	CODE(0FFFFH,0F860H,0FFFFH,0F860H,07FFFH,0B800H,07FFFH,0FC00H);
	CODE(03FFFH,0FE00H,01FFFH,0FE00H,01FFFH,0FE00H,00FFFH,0FC00H);
	CODE(00FFFH,0F800H,007FFH,0F800H,007FFH,0F800H,00FFFH,0F000H);
	CODE(00FFFH,0F000H,01FFFH,0C000H,03FF8H,00000H,03FF8H,00000H);
	CODE(00FF8H,00000H,003F8H,00000H,000F8H,00000H,00038H,00000H);
	CODE(04661H,06365H,0496DH,06700H,0A2A2H,0A2A2H,0A2A2H,0A2A2H);
	CODE(0A2A2H,0A2A2H,0A2A2H,0A2A2H,0A2A2H,0A2A2H,0A2A2H,0A2A2H); (*$P+*)
END FaceImg; (*$P-*)(*$S=*)(*$D=*)

PROCEDURE AlertDemo;
VAR
	i: SHORTINT;
BEGIN
	IF alert.ualert(1,2,'[0][1. Zeile][OK|Abbruch]')=2 THEN
		RETURN
	END;
	IF alert.ualert(1,2,'[1][1. Zeile][OK|Abbruch]')=2 THEN
		RETURN
	END;
	alert.display('[0][1. Zeile][]');
	evnt.timer(1000);
	alert.display('[1][1. Zeile][]');
	evnt.timer(1000);

	IF alert.ualert(1,2,'[0][1. Zeile|2. Zeile][OK|Abbruch]')=2 THEN
		RETURN
	END;
	IF alert.ualert(1,2,'[2][1. Zeile|2. Zeile][OK|Abbruch]')=2 THEN
		RETURN
	END;
	alert.display('[0][1. Zeile|2. Zeile][]');
	evnt.timer(1000);
	alert.display('[1][1. Zeile|2. Zeile][]');
	evnt.timer(1000);

	IF alert.ualert(1,2,'[0][1. Zeile|2. Zeile|3. Zeile][OK|Abbruch]')=2 THEN
		RETURN
	END;
	IF alert.ualert(1,2,'[3][1. Zeile|2. Zeile|3. Zeile][OK|Abbruch]')=2 THEN
		RETURN
	END;
	alert.display('[0][1. Zeile|2. Zeile|3. Zeile][]');
	evnt.timer(1000);
	alert.display('[1][1. Zeile|2. Zeile|3. Zeile][]');
	evnt.timer(1000);

	IF alert.ualert(1,2,'[0][1. Zeile|2. Zeile|3. Zeile|4. Zeile][OK|Abbruch]')=2 THEN
		RETURN
	END;
	IF alert.ualert(1,2,'[1][1. Zeile|2. Zeile|3. Zeile|4. Zeile][OK|Abbruch]')=2 THEN
		RETURN
	END;
	alert.display('[0][1. Zeile|2. Zeile|3. Zeile|4. Zeile][]');
	evnt.timer(1000);
	alert.display('[2][1. Zeile|2. Zeile|3. Zeile|4. Zeile][]');
	evnt.timer(1000);

	IF alert.ualert(1,2,'[0][1. Zeile|2. Zeile|3. Zeile|4. Zeile|5. Zeile][OK|Abbruch]')=2 THEN
		RETURN
	END;
	IF alert.ualert(1,2,'[3][1. Zeile|2. Zeile|3. Zeile|4. Zeile|5. Zeile][OK|Abbruch]')=2 THEN
		RETURN
	END;
	alert.display('[0][1. Zeile|2. Zeile|3. Zeile|4. Zeile|5. Zeile][]');
	evnt.timer(1000);
	alert.display('[1][1. Zeile|2. Zeile|3. Zeile|4. Zeile|5. Zeile][]');
	evnt.timer(1000);
	alert.remove;

	alert.Image := ADDRESS(FaceImg);
	i := alert.ualert(1,2,
		'[4][Aužerdem sind bis zu vier Kn”pfe und eigene Images m”glich.| |Die Breite ist nicht auf 30, sondern auf 80 Zeichen begrenzt!][OK|Ja|Aha|Doll]');
END AlertDemo;

(*-------- Demonstration des Selektors --------------------------------------*)

(*$E+*)
PROCEDURE GetSubItem(nr: SHORTINT; VAR item: STRING; user: ADDRESS);
VAR
	i: SHORTINT;
	s: ARRAY[0..15] OF CHAR;
BEGIN
	s := 'CHR(xxx) = " "';
	s[4] := CHR(nr DIV 100 + 60B);
	s[5] := CHR(nr DIV 10 MOD 10 + 60B);
	s[6] := CHR(nr MOD 10 + 60B);
	IF nr>0 THEN s[12] := CHR(nr) END;
	FOR i:=0 TO 14 DO item[i] := s[i] END
END GetSubItem;

PROCEDURE DoSelect;
BEGIN
	(* erst mal mit festen Strings *)
	REPEAT
	UNTIL select.str(' L„nderwahl ',
	' Baden-W�rttemberg| Bayern| Berlin| Brandenburg| Bremen| Hamburg| Hessen| Mecklenburg-Vorpommern| Niedersachsen| Nordrhein-Westfalen| Rheinland-Pfalz| Saarland| Sachsen| Sachsen-Anhalt| Schleswig-Holstein| Th�ringen',
	NIL,2)>=0;
	(* jetzt raffinierter mit einer Prozedur *)
	REPEAT
	UNTIL select.do(TRUE,'Zeichen',256,14,GetSubItem,NIL,64)>=0;
	(* erst mal mit festen Strings *)
END DoSelect;

(*-------- Demonstration der Dateiauswahl -----------------------------------*)

PROCEDURE DoXfsel;
VAR
	path,patt,file: ARRAY[0..79] OF CHAR;
BEGIN
(*	path := '.\*.PRG'; (* der Pfad wird automatisch expandiert *)*)
	path := '.\*.*'; (* der Pfad wird automatisch expandiert *)
	file := 'GEM_DEMO.PRG';
	REPEAT
	UNTIL xfsel.input(path,file,'Die erweiterte Dateiauswahl');
	xfsel.labels('PATH:','SELECT ','DRIVES:','OK','CANCEL');
	path := 'C:\'; patt := '*.APP,*.PRG,*.TOS,*.TTP'; file := '';
	REPEAT
	UNTIL xfsel.xinput(path,patt,file,'NOW IN ENGLISH!');
END DoXfsel;

PROCEDURE DoDemo();
BEGIN
	TheTree := 0; 						(* Mit Flag12-Dialog anfangen *)
	REPEAT
		Dialog(TIdx[TheTree]);	(* abhandeln...*)
	UNTIL TheTree<0
END DoDemo;

(*---------------------------------------------------------------------------*)

PROCEDURE Stretch;
VAR
	d: dial.tDial;
BEGIN
	dial.init(d,Form20);
	dial.stretch(d,vwk.charh+4,vwk.charh);
END Stretch;

(*--------------------------------------------------------------------*)

VAR
	MenuTree: objc.tpTree;
	d1,d2,d3: dial.tDial;
	T1,T2,T3: ARRAY[0..19] OF CHAR;
	D: ARRAY[0..3] OF dial.tDial;
	DeskTree: objc.tpTree;
	P2: pops.tPops;
	Sel2: ARRAY[0..1] OF BITSET;
(*	pstr: ARRAY[0..29] OF CHAR;*)
	pstr: ARRAY[0..79] OF CHAR;
	dr: AES.tRect;
	Msg: evnt.tMsg;
	cnt,
	MoX,MoY,Clicks: SHORTINT;
	MoState,KState,what: BITSET;
	Key: AES.tKey;
	Quit: BOOLEAN;
	(* Objekt-Demo: *)
	TheTree: SHORTINT;
	wrk: AES.tRect;
	TIdx: ARRAY[0..TMax] OF SHORTINT;
	TTit: ARRAY[0..TMax] OF xobj.tRStr;
BEGIN
	IF vwk.init() & rsrc.load('GEM_DEMO.RSC') THEN
		rsc.trnfm_all(MaxTree,MaxFrImg);
		inf.init;
		vst.alignment(vwk.hdl,vst.LeftJust,vst.TopLine,MoX,MoX);
		Stretch;						 (* Vorbereiten der Dialoge *)
		TIdx[ 0] := Form12	; TTit[ 0] := '  Submen�s...';
		TIdx[ 1] := Formedit; TTit[ 1] := '  Editieren...';
		TIdx[ 2] := Form17	; TTit[ 2] := '  Exttype 17...';
		TIdx[ 3] := Form18a ; TTit[ 3] := '  Exttype 18-1...';
		TIdx[ 4] := Form18b ; TTit[ 4] := '  Exttype 18-2...';
		TIdx[ 5] := Form18c ; TTit[ 5] := '  Exttype 18-3...';
		TIdx[ 6] := Form19	; TTit[ 6] := '  Exttype 19...';
		TIdx[ 7] := Form20	; TTit[ 7] := '  Exttype 20...';
		TIdx[ 8] := Form21	; TTit[ 8] := '  Exttype 21...';
		TIdx[ 9] := Form22	; TTit[ 9] := '  Exttype 22...';
		TIdx[10] := Form23a ; TTit[10] := '  Exttype 23-1...';
		TIdx[11] := Form23b ; TTit[11] := '  Exttype 23-2...';
		TIdx[12] := Form24	; TTit[12] := '  Exttype 24...';
		TIdx[13] := Form25	; TTit[13] := '  Exttype 25...';
(*$? gpb.PIN:
		(*
		 * f�r gpb.PIN werden in diesem Dialog die PinButtons demonstriert.
		 * Da vom Gebrauch eines eigenen Desktops aber im Zuge von MultiTOS
		 * und anderen Mehrprogramm-Plattformen abzuraten ist, sollte man
		 * dieses GEMplus-Feature nicht verwenden.
		 *)
		TIdx[14] := Form26	; TTit[14] := '  Exttype 26...';
*)
		rsrc.gaddr(rsrc.Tree,Menue,MenuTree);
		xmenu.create(MenuTree);
		cnt := 20; xmenu.setroll(MenuTree,Tool0,cnt,GetItem);
		xmenu.bar(MenuTree,TRUE,TRUE);
		rsrc.gaddr(rsrc.Tree,Desk,DeskTree);
		dial.init_pin(DeskTree,255,D);
		desk.install(DeskTree,' TSTwdial ');
		LoadDesk;
		IF desk.open(PAR.work,PAR.X,PAR.Y) THEN END;
		T1 := ' Dialog 1... ';
		wdial.create(d1,ADR(T1),React,D1,wdial.NoTree,wdial.NoTree);
		T2 := ' Dialog 2 ';
		wdial.create(d2,ADR(T2),React,D2,wdial.NoTree,wdial.NoTree);
		T3 := ' TSTwdial ';
		wdial.create(d3,ADR(T3),React,D3,D3menue,D3icon);
		xmenu.bar(d3.DMenu,TRUE,FALSE);
		wdial.move(d3,0,vwk.wrk.y);
		wdial.move(d2,vwk.xmax-d2.Tree^[0].pos.w,vwk.wrk.y);
		dial.init(D[0],D4);
		dial.init(D[1],D5);
		dial.init(D[2],Popmenu);
		dial.init(D[3],Setroll);
		list.create(d2,D2list,D2vslid,vwk.charh,0,32,DrawIt,
			ADR(Sel2),0,xobj.Sel0_n,NIL);
		list.create_hor(d2,D2list,D2hslid,vwk.charw,0,18);
		util.arr_setval(d2,D2arr,0,-999,999);
		pstr := 'A:|B:|C:|D:|E:|F:|G:|H:|I:';
		pops.create2(d2,D2pop,0,pstr,p2);
		mouse.arrow;
		MCnt := 0;
		IF wdial.open(d2,0) & wdial.open(d3,0) THEN
			Quit := FALSE;
			mouse.update(TRUE);
			REPEAT
				mouse.update(FALSE);
				what := evnt.multi({evnt.Keybd,evnt.Button,evnt.Mesag},2,{0},{0},
					FALSE,dr,FALSE,dr,Msg,0,MoX,MoY,MoState,KState,Key,Clicks);
				mouse.update(TRUE);
				IF (evnt.Keybd IN what)
				 & DoKey(Key,KState)
				 & wdial.keybd(Key,MoState,KState) THEN

				END;
				IF (evnt.Button IN what)
				 & wdial.button(Clicks,MoX,MoY,MoState,KState)
				 & dial.button(MoX,MoY,DoDial) THEN
					DoButton(MoX,MoY,Clicks)
				END;
				IF (evnt.Mesag IN what) THEN
				 IF desk.mesag(Msg)
				 & wdial.mesag(Msg) THEN
					IF Msg.type=evnt.Selected THEN
						DoMenu(Msg.title,Msg.entry)
					END
				 END
				END
			UNTIL Quit;
			mouse.update(FALSE)
		END;
		wdial.close_all;
		desk.close;
		xmenu.bar(MenuTree,FALSE,TRUE);
		xmenu.delete(MenuTree);
		xmenu.bar(d3.DMenu,FALSE,FALSE);
		SaveDesk;
		rsrc.free
	END
END GEM_DEMO.
		
	
	